package com.rgs.pay.yisheng.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.rgs.pay.entity.OrderRefundDO;
import com.rgs.pay.entity.SysPayKey;
import com.rgs.pay.service.OrderRefundService;
import com.rgs.pay.yisheng.dto.JsapiRequestDTO;
import com.rgs.pay.yisheng.util.RsaUtil;
import com.rgs.pay.yisheng.vo.YishengCommonRespVO;
import com.rgs.pay.yisheng.vo.YishengRefundCommonReqVO;
import com.rgs.pay.yisheng.vo.YishengRefundCommonRespVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.rgs.pay.yisheng.util.BasePayUtil.*;

/**
 * @program: com-rgs-parent
 * @description: 易生支付
 * @author: Mr.Ren
 * @create: 2022-12-02 11:05
 **/
public class YishengPayService {
    private static final Logger logger = LoggerFactory.getLogger(YishengPayService.class);

    @Resource
    OrderRefundService orderRefundService;

    /**
     * 易生微信/支付宝JSAPI原生支付
     *
     * @param pa         参数
     * @param sysPayKey  支付配置
     * @param payChannel 支付通道 支付宝 微信 银联等等WTJS1微 WAJS1支
     * @return
     */
    public Map<String, String> yishengJSAPIPay(Map<String, String> pa, SysPayKey sysPayKey, String payChannel) {
        String title = pa.get("title");
        System.out.println("======================" + title + "=====易生支付预下单开始==============================");
        Map<String, String> result = new HashMap<>();
        try {
            String body = pa.get("body");
            String openid = pa.get("openid");
            String userId = pa.get("userId");
            String attach = pa.get("attach");
            String totalFee = pa.get("total_fee");
            String outTradeNo = pa.get("out_trade_no");
            String notifyUrl = pa.get("notify_url");
            //data数据
            JsapiRequestDTO.DataBean data = new JsapiRequestDTO.DataBean();
            data.setOrgBackUrl(notifyUrl);
            data.setOrgFrontUrl(notifyUrl);
            data.setTradeCode("WTJS1");
            data.setTradeAmt(Integer.parseInt(totalFee));
            data.setTimeoutMinutes(300);
            data.setOrderInfo(body);

            if ("WTJS1".equals(payChannel)) {
                data.setPayerId(openid);
                data.setWxSubAppid(sysPayKey.getWxAppId());
            } else if ("WAJS1".equals(payChannel)) {
                data.setPayerId(userId);
            }

            //签名
            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(data);
            String newData = getReqStr(jsonObject);
            Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, sysPayKey.getAliPrivateKey(), null);
            String singStr = Base64.getEncoder().encodeToString(sign.sign(newData.getBytes()));

            //下单参数
            JsapiRequestDTO commonReq = new JsapiRequestDTO();
            commonReq.setOrgId(sysPayKey.getWxKey());
            commonReq.setOrgMercode(sysPayKey.getWxMchId());
            commonReq.setOrgTermno(sysPayKey.getWxAppSecret());
            commonReq.setOrgTrace(outTradeNo);
            commonReq.setSignType(SIGN_TYPE_RSA256);//固定
            commonReq.setData(data);
            commonReq.setSign(singStr);
            //附加消息 附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
            commonReq.setOrgInfo(attach + "-" + sysPayKey.getDeptId());

            System.out.println("易生请求参数：" + commonReq);
            //下单
            String commonReqJsonStr = JSONUtil.toJsonStr(commonReq);
            String url = "https://t-wapi.bhecard.com:8443/standard/jsapi";
            String responseResult = HttpUtil.post(url, commonReqJsonStr);

            //下单结果
            YishengCommonRespVO commonRespVO = JSONUtil.toBean(responseResult, YishengCommonRespVO.class);
            System.out.println("易生返回结果：" + commonRespVO);

            //1.判断易生系统返回
            String sysRetcode = commonRespVO.getSysRetcode();
            if (StrUtil.isNotEmpty(sysRetcode) && StrUtil.equals(sysRetcode, "000000")) {
                //2.验签
                JSONObject responseData = (JSONObject) JSONObject.toJSON(commonRespVO.getData());
                boolean verifyFlag = RsaUtil.verifyBySHA256WithRSA(getReqStr(responseData), commonRespVO.getSign(), sysPayKey.getAliPublicKey());
                if (verifyFlag) {
                    //判断微信返回
                    String finRetcode = commonRespVO.getData().getFinRetcode();
                    if (StrUtil.equals(finRetcode, "99") || StrUtil.equals(finRetcode, "00")) {
                        if ("WTJS1".equals(payChannel)) {
                            //下单成功，解析微信返回的参数
                            String wxWcPayData = commonRespVO.getData().getWxWcPayData();
                            if (StrUtil.isNotEmpty(wxWcPayData)) {
                                result.put("code", "SUCCESS");
                                result.put("msg", "下单成功");
                                result.put("data", wxWcPayData);
                                result.put("payType", "yisheng_wechat");
                                //系统的订单号
                                result.put("out_trade_no", outTradeNo);
                            } else {
                                logger.error("rgs-wxWcPayData为空");
                                result.put("code", "ERROR");
                                result.put("msg", "下单失败");
                            }
                        } else if ("WAJS1".equals(payChannel)) {
                            //下单成功，解析微信返回的参数
                            String pcTrace = commonRespVO.getData().getPcTrace();
                            if (StrUtil.isNotEmpty(pcTrace)) {
                                result.put("code", "SUCCESS");
                                result.put("msg", "下单成功");
                                result.put("data", pcTrace);
                                result.put("payType", "yisheng_ali");
                                //系统的订单号
                                result.put("out_trade_no", outTradeNo);
                            } else {
                                //交易错误，下单失败
                                result.put("code", "ERROR");
                                result.put("msg", "下单失败");
                            }
                        }

                    } else {
                        logger.error("rgs-finRetcode不是00或99，" + finRetcode);
                        result.put("code", "ERROR");
                        result.put("msg", "下单失败");
                    }


                } else {
                    logger.error("rgs-验签失败");
                    result.put("code", "ERROR");
                    result.put("msg", "下单失败");
                }
            } else {
                logger.error("rgs-sysRetcode不是000000," + sysRetcode);
                result.put("code", "ERROR");
                result.put("msg", "下单失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            result.put("code", "ERROR");
            result.put("msg", "下单失败");
        }
        System.out.println("======================" + title + "=====易生支付预下单结束==============================");
        return result;
    }


    /**
     * 易生支付退款
     *
     * @param refundData 相关参数
     * @param sysPayKey  支付配置
     * @return success成功 error失败
     */
    private Map<String, String> yishengPayRefund(Map<String, String> refundData, SysPayKey sysPayKey) {
        Map<String, String> result = new HashMap<>();
        //退款的流水号，对应退款表out_refund_no
        String out_refund_no = getTradeNoByTime() + "ysRefund";
        //		易生的金额以分为单位，需要乘100
        String total_fee = new BigDecimal(refundData.get("total_fee")).multiply(new BigDecimal(100)).intValue() + "";
        String refund_fee = new BigDecimal(refundData.get("refund_fee")).multiply(new BigDecimal(100)).intValue() + "";
        String order_no = refundData.get("order_no");
        String orderId = refundData.get("orderId");
        String type = refundData.get("type");
        String deptId = refundData.get("deptId");


        //封装请求参数
        YishengRefundCommonReqVO commonReqVO = new YishengRefundCommonReqVO();
        commonReqVO.setOrgId(sysPayKey.getWxKey());
        commonReqVO.setOrgMerCode(sysPayKey.getWxMchId());
        commonReqVO.setOrgTermNo(sysPayKey.getWxAppSecret());
        //每次交易都会有流水，保证唯一；交易的流水定义为订单号，退款也需要生成这个号码，对应退款表中的out_refund_no
        commonReqVO.setOrgTrace(out_refund_no);

        commonReqVO.setSignType(SIGN_TYPE_RSA256);
        //内部数据
        YishengRefundCommonReqVO.BizDataBean bizDataBean = new YishengRefundCommonReqVO.BizDataBean();
        //退款的订单号，对应订单表的no
        bizDataBean.setOriOrgTrace(order_no);
        //退款金额 分
        bizDataBean.setTransAmt(refund_fee);
        //data
        commonReqVO.setBizData(bizDataBean);
        //签名
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(bizDataBean);
        String newData = getReqStr(jsonObject);
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, sysPayKey.getAliPrivateKey(), null);
        String singStr = Base64.getEncoder().encodeToString(sign.sign(newData.getBytes()));
        commonReqVO.setSign(singStr);
        String commonReqJsonStr = JSONUtil.toJsonStr(commonReqVO);
        try {
            //退款
            String url = "https://t-wapi.bhecard.com:6111/ledger/mposrefund";
            String responseResult = HttpUtil.post(url, commonReqJsonStr);
            YishengRefundCommonRespVO commonRespVO = JSONUtil.toBean(responseResult, YishengRefundCommonRespVO.class);
            //1.判断易生系统返回
            String sysRetcode = commonRespVO.getSysRetCode();
            if (StrUtil.isNotEmpty(sysRetcode) && StrUtil.equals(sysRetcode, "000000")) {
                YishengRefundCommonRespVO.BizDataBean bizData = commonRespVO.getBizData();
                //验签
                JSONObject responseData = (JSONObject) JSONObject.toJSON(bizData);
                boolean verify = RsaUtil.verifyBySHA256WithRSA(getReqStr(responseData), commonRespVO.getSign(), sysPayKey.getAliPublicKey());
                if (verify) {
                    //验签成功
                    if (StrUtil.equals(bizData.getTradeRetCode(), "00")) {
                        //易生退款直接退款成功，不像微信那样需要回调通知
                        OrderRefundDO orderRefund = new OrderRefundDO();
                        orderRefund.setCreateTime(new Date());
                        orderRefund.setRefundMoney(new BigDecimal(refundData.get("refund_fee")));
                        orderRefund.setStatus("success");
                        orderRefund.setReason(refundData.get("reason"));
                        orderRefund.setCreateUser(refundData.get("createUser"));
                        orderRefund.setTotalMoney(new BigDecimal(refundData.get("total_fee")));
                        orderRefund.setOrderId(refundData.get("orderId"));
                        orderRefund.setOutTradeNo(bizData.getOriOrgTrace());//平台支付订单号
                        orderRefund.setOutRefundNo(out_refund_no);//退款流水号
                        orderRefund.setTransactionId(bizData.getPcTrace());//微信/支付宝返回的号
                        orderRefund.setRefundTime(new Date());
                        orderRefund.setParkId(refundData.get("parkId"));
                        orderRefund.setDeptId(Long.parseLong(deptId));
                        orderRefund.setRefundPlatform("yishengPay");
                        orderRefund.setRefundType(refundData.get("refundType"));
                        orderRefundService.insertOrderRefundTbl(orderRefund);
                        logger.error("订单号：" + bizData.getOriOrgTrace() + ",退款成功");
                        result.put("code", "SUCCESS");
                        result.put("msg", "退款成功");
                    } else {
                        logger.error("订单号：" + bizData.getOriOrgTrace() + ",退款交易失败:TradeRetCode=" + bizData.getTradeRetCode() + ",TradeRetMsg" + bizData.getTradeRetMsg());
                        result.put("code", "ERROR");
                        result.put("msg", "退款交易失败");
                    }
                } else {
                    logger.error("退款验签未通过");
                    result.put("code", "ERROR");
                    result.put("msg", "退款验签未通过");
                }
            } else {
                logger.error("系统返回失败rgs-sysRetcode不是000000," + sysRetcode);
                result.put("code", "ERROR");
                result.put("msg", "退款失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("易生退款异常");
            result.put("code", "ERROR");
            result.put("msg", "易生退款异常");
        }
        return result;

    }

}
